package com.shb.jutils.commons;


import java.time.Duration;
import java.util.Date;
import java.util.Iterator;

/**
 * 日期迭代器
 * <p>从开始日期按照指定的周期迭代，每次迭代返回一个元组【开始时间，当前迭代尾时间】</p>
 *
 * 当前迭代尾时间 必须 小于或者等于迭代的最大结束时间
 * <p>
 *
 * <p>假设从2021-11-11 10:00:00,2021-11-12 10:00:00， 周期一天， 返回结果为：<br>
 * (2021-11-11 10:00:00,2021-11-12 10:00:00)
 * </p>
 *
 * <p>
 *
 * <p>假设从2021-11-11 10:00:00,2021-11-12 12:00:00， 周期一天， 返回结果为：<br>
 * (2021-11-11 10:00:00,2021-11-12 10:00:00)
 * (2021-11-12 10:00:00,2021-11-12 12:00:00)
 * </p>
 */
public class DateIterator implements Iterator<Pair<String, String>> {
    private Date from;
    private Date to;
    private Duration period;
    private boolean reset = true;

    public static DateIterator of(String from, String to, String duration) {
        return new DateIterator(from, to, DurationUtil.parseDuration(duration));
    }

    public DateIterator(String from, String to, Duration period) {
        this.from = parse(from);
        this.to = parse(to);
        this.period = period;
    }

    private Date currentStart;
    private Date currentEnd;

    @Override
    public boolean hasNext() {
        if (this.currentEnd != null && this.currentEnd.compareTo(to) >= 0) {
            return false;
        }

        if (reset) {
            reset = false;
            this.currentStart = from;
            this.currentEnd = min(DateUtil.addMillis(this.from, (int) period.toMillis()), to);
        } else {
            this.currentStart = DateUtil.addMillis(this.currentStart, (int) period.toMillis());
            this.currentEnd = min(DateUtil.addMillis(this.currentStart, (int) period.toMillis()), to);
        }
        return this.currentEnd.compareTo(to) <= 0;
    }

    @Override
    public Pair<String, String> next() {
        return Pair.of(format(currentStart), format(currentEnd));
    }

    private String format(Date date) {
        return DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
    }

    private Date parse(String dateStr) {
        return DateUtil.parse(dateStr, "yyyy-MM-dd HH:mm:ss","yyyy-MM-dd");
    }

    private Date min(Date d1, Date d2) {
        return d1.after(d2) ? d2 : d1;
    }


    public static void main(String[] args) {
        DateIterator dateIterator = DateIterator.of("2021-11-11 10:00:00", "2021-11-12 10:00:12", "10m");
        while (dateIterator.hasNext()) {
            Pair<String, String> next = dateIterator.next();
            System.out.println(next);
        }
    }
}
